home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / New System Software Extensions / QuickDraw™ GX v1.0ß2 / Sample Code / Printing Samples / Printer Drivers… / ImageWriterLQ / OldAPIMessageIntf.c < prev    next >
Encoding:
Text File  |  1993-09-13  |  19.4 KB  |  713 lines  |  [TEXT/MPS ]

  1. /*---------------------------------------------------------------------------
  2. FILENAME
  3.     OldAPIMessageIntf.c
  4.  
  5. DESCRIPTION
  6.     This module contains the routines which implement the old API messages
  7.     that the ImageWriter LQ driver overrides.  Much of the logic in this
  8.     module was gleaned from the original ImageWriter LQ driver, and so
  9.     some of the calculations may seem a little strange.  In order to maintain
  10.     compatibility with the old driver's logic, we must preserve much of the
  11.     old logic.
  12.         
  13. COPYRIGHT
  14.      Copyright Apple Computer, Inc. 1992
  15.      All rights reserved. 
  16.         
  17.     9/13/93 - dmh - Updated for b2 seed.
  18.         
  19. INTERFACE ROUTINES:
  20.  
  21.     SD_PrValidate
  22.     SD_ConvertPrintRecordTo
  23.     SD_ConvertPrintRecordFrom
  24.  
  25. -------------------------------------------------------------------------------- */
  26.  
  27. // Include the standard Mac header files 
  28. #include "MacIncludes.h"
  29.  
  30. // Include the new QuickDraw GX graphics header files 
  31. #include <graphics routines.h>
  32. #include <graphics libraries.h>
  33. #include <math routines.h>
  34.  
  35. // Include the required Printing Manager header files 
  36. #include <PrintingManager.h>
  37. #include <PrintingMessages.h>
  38. #include <PrintingDrivers.h>
  39. #include <Collections.h>
  40. #include <Messages.h>
  41. #include <PrintingResTypes.h>
  42. #include <PrintingErrors.h>
  43. #include <Exceptions.h>
  44.  
  45. // Include the internal driver constants and types used by this module 
  46. #include "Resources.h"
  47. #include "OldAPIMessageIntf.h"
  48.  
  49.  
  50. /***************************************************************************************
  51. *                                         INTERNAL ROUTINES                                                    *
  52. ***************************************************************************************/
  53.  
  54.  
  55. /****************************************************************************************
  56.  
  57.                             OldLQ_CiMetrics
  58.                             
  59.     function:
  60.                 This function takes an old style print record and massages its fields in 
  61.                 a manner equivalent to the old style LQ driver.  This logic is basically
  62.                 lifted from the old LQ driver.
  63.                 
  64.     parameters:                
  65.                 hPrint        target print record whose fields are to be updated
  66.  
  67.     returns:
  68.                 none
  69.     
  70. ****************************************************************************************/
  71. void OldLQ_CiMetrics(THPrint    hPrint)
  72. {
  73.     TPPrint    pPrint = *hPrint;
  74.     short        dhPage;
  75.     short        dvPage;
  76.     short        dhPaper;
  77.     short        dvPaper;
  78.     short        hOff;
  79.     short        vOff;
  80.     short        cPlaten;
  81.     short        gap;
  82.     short        scanBits;
  83.     short        maxH;
  84.     short        wDev;
  85.  
  86.     cPlaten = kPlaten8;
  87.     if ( pPrint->prStl.iPageH > (9 * kMysticPaperFract) ) 
  88.     {
  89.         cPlaten = kPlaten15;                     // platen width in half inches
  90.     }
  91.  
  92.     wDev = pPrint->printX[1];
  93.     pPrint->prInfo.iDev = 0;                     // Use screen device for lo res or fake hi res
  94.     if ( !TestBit(wDev, kResSetBit) )         // not fResSet
  95.     {                                     
  96.         pPrint->prInfo.iVRes = 72;
  97.         pPrint->prInfo.iHRes = 72;
  98.     }                                         
  99.     else
  100.     if ( pPrint->prInfo.iVRes = 216 )    // Real HiRes
  101.     {
  102.         wDev |= kHighResBit;                //    force "hi res"
  103.         wDev &= ~k66PercentReducBit;         // clear 66% Reduction off
  104.         wDev &= ~k33PercentReducBit;         // clear 33% Reduction off
  105.         pPrint->printX[1] = wDev;
  106.     }
  107.  
  108.     // Calculate rPaper height in Y
  109.     dvPaper = (pPrint->prStl.iPageV * pPrint->prInfo.iVRes) / kMysticPaperFract;
  110.     
  111.     // Calculate rPage height in Y
  112.     gap = (60 * pPrint->prInfo.iVRes) / kMysticPaperFract;
  113.             
  114.     if ( TestBit(wDev, kScrollBit) )
  115.     {
  116.         gap = 0;
  117.     }
  118.             
  119.     // force page height to be an integral number of head scans
  120.     dvPage = (( dvPaper - gap ) / 24) * 24;
  121.         
  122.     // Calculate rPaper width in dots
  123.     dhPaper = (pPrint->prStl.iPageH * pPrint->prInfo.iHRes) / kMysticPaperFract;
  124.  
  125.     // Calculate max width in dots
  126.         
  127.     maxH = ( cPlaten * pPrint->prInfo.iHRes ) >> 1;
  128.     if (maxH > dhPaper)
  129.     {
  130.         maxH = dhPaper;
  131.     }
  132.     scanBits = ( maxH >> 4 ) << 4;    // force to word boundary
  133.  
  134.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Portrait orientation
  135.     {
  136.         dhPage = scanBits;
  137.     }
  138.     else    //    Landscape orientation: switch height and width
  139.     {
  140.         dhPage = dvPage;
  141.         dvPage = scanBits;
  142.     }
  143.  
  144.     SetRect(&pPrint->prInfo.rPage, 0, 0, dhPage, dvPage);
  145.  
  146.     // Calculate rPaper offsets, & set rPaper
  147.     
  148.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Portrait orientation
  149.     {
  150.         hOff = (dhPage - dhPaper) >> 1; // Note: Negative
  151.         vOff = -gap;
  152.     }
  153.     else    //    Landscape orientation: switch height and width
  154.     {
  155.         short        iTemp;
  156.  
  157.         iTemp = dhPaper;
  158.         dhPaper = dvPaper;
  159.         dvPaper = iTemp;
  160.  
  161.         hOff = - gap;
  162.         vOff = (dvPage - dvPaper) >> 1;
  163.     }
  164.     SetRect(&pPrint->rPaper, hOff, vOff, dhPaper + hOff, dvPaper + vOff);
  165.         
  166.     // Calculate rPage height in dots, & set rPage
  167.     //If 66% reduction, triple both rectangles: ( Page and Paper )
  168.  
  169.     if ( TestBit(wDev, k66PercentReducBit) )    //    66% reduction selected
  170.     {
  171.         pPrint->prInfo.rPage.right *= 3;
  172.         pPrint->prInfo.rPage.bottom *= 3;
  173.         
  174.         pPrint->rPaper.top *= 3;
  175.         pPrint->rPaper.left *= 3;
  176.         pPrint->rPaper.right *= 3;
  177.         pPrint->rPaper.bottom *= 3;
  178.     }
  179.  
  180.     // If 33% reduction, scale both rectangles: ( Page and Paper )
  181.     if ( TestBit(wDev, k33PercentReducBit) )    //    33% reduction selected
  182.     {
  183.         pPrint->prInfo.rPage.right = FixRound( FixMul( lScale, (pPrint->prInfo.rPage.right << 16) ));
  184.         pPrint->prInfo.rPage.bottom = FixRound( FixMul( lScale, (pPrint->prInfo.rPage.bottom << 16) ));
  185.         
  186.         pPrint->rPaper.top = FixRound( FixMul( lScale, (pPrint->rPaper.top << 16) ));
  187.         pPrint->rPaper.left = FixRound( FixMul( lScale, (pPrint->rPaper.left << 16) ));
  188.         pPrint->rPaper.right = FixRound( FixMul( lScale, (pPrint->rPaper.right << 16) ));
  189.         pPrint->rPaper.bottom = FixRound( FixMul( lScale, (pPrint->rPaper.bottom << 16) ));
  190.     }
  191.                 
  192.     if ( TestBit(wDev, kDraftBit) )    //    Draft bits selected
  193.     {
  194.         pPrint->prJob.bJDocLoop = bDraftLoop;
  195.     }
  196.  
  197.     // Copy WDEV field back to old position for apps that read these flags
  198.     
  199.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )
  200.     {
  201.         wDev |= kPortraitBit;
  202.     }
  203.     else
  204.     {
  205.         wDev &= ~kPortraitBit;
  206.     }
  207.     
  208.     pPrint->printX[1] = wDev;
  209.     pPrint->prStl.wDev = wDev;
  210. }
  211. /* OldLQ_CiMetrics */
  212.  
  213.  
  214. /****************************************************************************************
  215.  
  216.                             OldLQ_CiXMetrics
  217.                             
  218.     function:
  219.                 This function takes an old style print record and massages the PrInfoPT and
  220.                 PrXInfo fields in a manner equivalent to the old style LQ driver.  This logic 
  221.                 is basically lifted from the old LQ driver.
  222.                 
  223.     parameters:                
  224.                 hPrint        target print record whose fields are to be updated
  225.  
  226.     returns:
  227.                 none
  228.     
  229. ****************************************************************************************/
  230. void OldLQ_CiXMetrics(THPrint    hPrint)
  231. {
  232.     TPPrint        pPrint = *hPrint;
  233.     short        iScans;
  234.     short        iDevExtra;
  235.  
  236.     pPrint->prInfoPT = pPrint->prInfo; // Start with a straight copy
  237.  
  238.     pPrint->prXInfo.bPatScale = 0;
  239.  
  240.     if ( !TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Landscape mode
  241.     {
  242.         pPrint->prJob.bJDocLoop = bSpoolLoop; // Force spooling for landscape
  243.     }
  244.  
  245.     if ( TestBit(pPrint->printX[1], k66PercentReducBit) || TestBit(pPrint->printX[1], k33PercentReducBit) ) // 33% or 66% reduction
  246.     {
  247.         pPrint->printX[1] &= ~kHighResBit;        //    Clear the high-res bit
  248.         
  249.         if ( TestBit(pPrint->printX[1], k33PercentReducBit) )    // If 33% Reduction ONLY
  250.         {
  251.             pPrint->prXInfo.bPatScale = 2;         // Pattern double
  252.             
  253.             // SCALE 2X FOR 33% REDUCTION CASE
  254.             pPrint->prInfoPT.rPage.right <<= 1;
  255.             pPrint->prInfoPT.rPage.bottom <<= 1;
  256.         }
  257.     }
  258.  
  259.     if ( TestBit(pPrint->printX[1], kHighResBit) )    //    High resolution; triple everything
  260.     {
  261.         if ( !TestBit(pPrint->printX[1], kResSetBit) )    //    App hasn't set imaging resolution
  262.         {
  263.             pPrint->prInfoPT.iHRes *= 3;
  264.             pPrint->prInfoPT.iVRes *= 3;
  265.             pPrint->prInfoPT.rPage.right *= 3;
  266.             pPrint->prInfoPT.rPage.bottom *= 3;
  267.         }
  268.         
  269.         pPrint->prXInfo.bPatScale = 3;         // Pattern triple ** NOT VALID QD ** Intercept in PrBand
  270.         pPrint->prInfoPT.iDev = 0xFD00;         // For QD's char spacing adjustment
  271.     }
  272.  
  273.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )    //    Portrait mode
  274.     {
  275.         pPrint->prXInfo.iBandH = pPrint->prInfoPT.rPage.right;
  276.         pPrint->prXInfo.iBandV = 48;                                     // i8xBandScans = 24 * 2
  277.         iScans = pPrint->prInfoPT.rPage.bottom;
  278.         pPrint->prXInfo.scan = scanTop2Bottom;
  279.         iDevExtra = pPrint->prXInfo.iBandH;
  280.     }
  281.     else    //    Landscape mode
  282.     {
  283.         pPrint->prXInfo.iBandH = 48;                                     // i8xBandScans = 24 * 2;
  284.         pPrint->prXInfo.iBandV = pPrint->prInfoPT.rPage.bottom;
  285.         iScans = pPrint->prInfoPT.rPage.right;
  286.         pPrint->prXInfo.scan = scanLeft2Right;
  287.         iDevExtra = pPrint->prXInfo.iBandV;
  288.     }
  289.  
  290.     pPrint->prXInfo.iRowBytes = pPrint->prXInfo.iBandH >> 3;     // Must be even!
  291.     pPrint->prXInfo.iBands = ( iScans + 48 - 1 ) / 48;
  292.     
  293.     // Size a scan work buffer
  294.     pPrint->prXInfo.iDevBytes = ( pPrint->prXInfo.iRowBytes * pPrint->prXInfo.iBandV ) + ( iDevExtra * 3 ); 
  295.  
  296.     // Copy WDEV field back to old position for apps that read these flags
  297.     pPrint->prStl.wDev = pPrint->printX[1];
  298. }
  299. /* OldLQ_CiXMetrics */
  300.  
  301.  
  302. /****************************************************************************************
  303.  
  304.                             UpdatePrintRecord
  305.                             
  306.     function:
  307.                 This function updates the print record based upon the application's
  308.                 calls to PrGeneral.
  309.                 
  310.     parameters:                
  311.                 hPrint            print record to update
  312.                 
  313.     returns:
  314.                 none
  315.     
  316. ****************************************************************************************/
  317. void UpdatePrintRecord(THPrint hPrint)
  318. {
  319.     // emulate the old metric calculations        
  320.     OldLQ_CiMetrics(hPrint);
  321.     OldLQ_CiXMetrics(hPrint);
  322. }
  323. /* UpdatePrintRecord */
  324.  
  325.  
  326.  
  327. /***************************************************************************************
  328. *                                         INTERFACE ROUTINES                                                     *
  329. ***************************************************************************************/
  330.  
  331. /****************************************************************************************
  332.  
  333.                             SD_PrValidate
  334.                             
  335.     function:
  336.                 This function validates the print record.  If the passed-in print record contains
  337.                 valid information (see below), then it's updated based upon the application's
  338.                 calls to PrGeneral and the return code is true.
  339.                 Otherwise, the print record is defaulted (with PrintDefault), and the 
  340.                 return value is false.
  341.                 
  342.                 Validation:
  343.                     The upper byte of the PrintX[1] field must be the ID of the device 
  344.                         (kLQRefNum in OldAPIMessageIntf.h).
  345.                     
  346.                     The version of the print record must be current
  347.                         (oldIWLQPrintRecordVersion in Resources.h)
  348.                     
  349.                     (For new print records, we will validate all of the fields which are 
  350.                      public (e.g., paper size), not just these fields)
  351.                 
  352.     parameters:                
  353.                 hPrint                    print record to validate
  354.                 wasChanged                returns true if print record was invalid; false otherwise
  355.                 
  356.     returns:
  357.                 OSErr
  358.     
  359. ****************************************************************************************/
  360. OSErr SD_PrValidate(THPrint hPrint, Boolean *wasChanged)
  361. {
  362.     short        wDev;                        // device specific stuff in this word
  363.     Boolean        returnVal = true;        // initialize return value to "invalid"
  364.                                             //     Why is true == "invalid"? Nobody knows!
  365.     
  366.     // check the wDev.  The upper byte must be equal to kLQRefNum.  We get the
  367.     //  wDev, and shift wDev DOWN eight.
  368.         
  369.     wDev =  (*hPrint)->printX[1];
  370.     wDev >>= 8;                                // get just the device ID
  371.  
  372.  
  373.     // If the device id is equal, then check the version number of the print record.
  374.     //    Only if that is also equal to the current version, will we return false (valid).
  375.         
  376.     if (wDev == kLQRefNum)
  377.         if ( (*hPrint)->iPrVersion == oldIWLQPrintRecordVersion )
  378.             returnVal = false;
  379.             
  380.  
  381.     // If the print record is not valid, then return the default print record.
  382.     // Otherwise, update the print record, based on the application's calls
  383.     // to PrGeneral.
  384.  
  385.     if (returnVal)
  386.         PrintDefault(hPrint);
  387.     else
  388.         UpdatePrintRecord(hPrint);
  389.         
  390.     *wasChanged = returnVal;
  391.     
  392.     return(noErr);
  393. }
  394. /* SD_PrValidate */
  395.  
  396.  
  397. /****************************************************************************************
  398.  
  399.                             SD_ConvertPrintRecordTo
  400.                             
  401.     function:     
  402.                 SD_ConvertPrintRecordTo converts the fields of the print record for
  403.                 the device into the universal print record format.  
  404.                 
  405.     parameters:    
  406.                 hPrint        print record to convert to universal format
  407.     
  408.     returns:
  409.                 OSErr
  410.     
  411. ****************************************************************************************/
  412. OSErr SD_ConvertPrintRecordTo(THPrint hPrint)
  413. {
  414.     gxUniversalPrintRecordPtr    pUniv;
  415.     TPPrint                         pPrint;
  416.     short                        options = 0;
  417.  
  418.     pUniv = (gxUniversalPrintRecordPtr) *hPrint;
  419.     pPrint = *hPrint;
  420.     
  421.     // Convert paper feed settings (old and univ setting are switched)
  422.  
  423.     if ( pPrint->prStl.feed == oldPRECAutoFeed )
  424.         pUniv->feed = gxAutoFeed;
  425.     else
  426.         pUniv->feed = gxManualFeed;
  427.     
  428.     // Fix up the actualCopies field
  429.     pUniv->actualCopies = pPrint->prJob.iCopies;
  430.     
  431.     // Determine the new options field settings
  432.  
  433.     if ( TestBit(pPrint->prStl.wDev, kScrollBit) )
  434.         options |= gxBiggerPages;
  435.         
  436.     pUniv->options = options;
  437.  
  438.     
  439.     // Now determine the scaling factor, if any, and designate the proper dialog button that
  440.     // corresponds to the scaling factor.  The userCluster1 field specifies the dialog button.
  441.     
  442.     if ( TestBit(pPrint->prStl.wDev, k66PercentReducBit) )
  443.     {
  444.         pUniv->reduction = 66;
  445.         pUniv->userCluster1 = 1;
  446.     }
  447.     else 
  448.     if ( TestBit(pPrint->prStl.wDev, k33PercentReducBit) )
  449.     {
  450.         pUniv->reduction = 33;
  451.         pUniv->userCluster1 = 0;
  452.     }
  453.     else     //    T => No scaling being performed
  454.     {
  455.         pUniv->reduction = 100;
  456.         pUniv->userCluster1 = 2;
  457.     }
  458.     
  459.  
  460.     // Set the orientation properly
  461.  
  462.     if ( TestBit(pPrint->prStl.wDev, kPortraitBit) )
  463.         pUniv->orientation = gxPortraitOrientation;
  464.     else
  465.         pUniv->orientation = gxLandscapeOrientation;
  466.  
  467.  
  468.     // Determine the quality setting
  469.     
  470.     if ( TestBit(pPrint->prStl.wDev, kHighResBit) )    //    T => Print in best quality
  471.     {
  472.         pUniv->qualityMode = gxBestQuality;
  473.     }
  474.     else
  475.     if ( pPrint->prJob.bJDocLoop == spool )    //    T => Print with faster quality
  476.     {
  477.         pUniv->qualityMode = gxFasterQuality;
  478.     }
  479.     else    //    T => Print with draft quality
  480.         pUniv->qualityMode = gxDraftQuality;
  481.     
  482.     
  483.     // Set the first tray and remaining tray fields
  484.     
  485.     if ( (pPrint->printX[0] & 0x0003) > 0 )    //    T => A first tray has been specified
  486.     {
  487.         switch ( pPrint->printX[0] & 0x0003 )
  488.         {
  489.             case    tray1:    pUniv->firstTray = gxFirstTray;        break;
  490.             case    tray2:    pUniv->firstTray = gxSecondTray;    break;
  491.             case    tray3:    pUniv->firstTray = gxThirdTray;        break;
  492.             default:        pUniv->firstTray = gxFirstTray;        break;
  493.         }
  494.     }
  495.     else
  496.         pUniv->firstTray = gxFirstTray;
  497.  
  498.     if ( (pPrint->printX[0] & 0x000C) > 0 )    //    T => A remaining tray has been specified
  499.     {
  500.         switch ( pPrint->printX[0] & 0x000C )
  501.         {
  502.             case    tray1:    pUniv->remainingTray = gxFirstTray;    break;
  503.             case    tray2:    pUniv->remainingTray = gxSecondTray; break;
  504.             case    tray3:    pUniv->remainingTray = gxThirdTray;    break;
  505.             default:        pUniv->remainingTray = gxFirstTray;    break;
  506.         }
  507.     }
  508.     else
  509.         pUniv->remainingTray = gxFirstTray;
  510.  
  511.     
  512.     // Set the headMotion field's value
  513.     
  514.     if ( TestBit(pPrint->prStl.wDev, kBiDirBit) )    //    T => Print in bidirectional mode
  515.     {
  516.         pUniv->headMotion = gxBidirectionalMotion;
  517.     }
  518.     else
  519.         pUniv->headMotion = gxUnidirectionalMotion;
  520.  
  521.         
  522.     // Always assign these fields explicit values to ensure they don't cause problems
  523.     
  524.     pUniv->coverPage         = gxNoCoverPage;
  525.     pUniv->saveFile         = gxNoFile;
  526.     
  527.     return(noErr);
  528. }
  529. /* SD_ConvertPrintRecordTo */
  530.  
  531.  
  532. /****************************************************************************************
  533.  
  534.                             SD_ConvertPrintRecordFrom
  535.                             
  536.     function:     
  537.                 SD_ConvertPrintRecordFrom converts the fields of the print record in 
  538.                 universal print record format into the print record format for the
  539.                 specific device. 
  540.                 
  541.     parameters:    
  542.                 hPrint        print record to convert to device specific format
  543.     
  544.     returns:
  545.                 OSErr
  546.     
  547. ****************************************************************************************/
  548. OSErr SD_ConvertPrintRecordFrom(THPrint hPrint)
  549. {
  550.     gxUniversalPrintRecordPtr    pUniv;
  551.     TPPrint                         pPrint;
  552.     short                        newWDev = kLQRefNum << 8;
  553.  
  554.     pUniv = (gxUniversalPrintRecordPtr) *hPrint;
  555.     pPrint = *hPrint;
  556.     
  557.     // Convert paper feed settings (old and univ setting are switched)
  558.  
  559.     if ( pUniv->feed == gxAutoFeed )
  560.         pPrint->prStl.feed = oldPRECAutoFeed;
  561.     else
  562.         pPrint->prStl.feed = oldPRECManualFeed;
  563.  
  564.  
  565.     // Fix up the actualCopies field
  566.     pPrint->prJob.iCopies = pUniv->actualCopies;
  567.     
  568.     
  569.     // Determine the new wDev flag settings
  570.     
  571.     if ( TestBit(pUniv->options, gxBiggerPages) )
  572.         newWDev |= kScrollBit;
  573.         
  574.     if (pUniv->headMotion == gxBidirectionalMotion)
  575.         newWDev |= kBiDirBit;
  576.         
  577.     switch( pUniv->userCluster1 )    //    Based on the scaling dialog button setting, set the scaling factor
  578.     {
  579.         case 2:        //    Full size
  580.             break;
  581.             
  582.         case 1:
  583.             newWDev |= k66PercentReducBit;
  584.             break;
  585.             
  586.         case 0:
  587.             newWDev |= k33PercentReducBit;
  588.             break;
  589.     }
  590.     
  591.     if (pUniv->orientation == gxPortraitOrientation)
  592.         newWDev |= kPortraitBit;
  593.  
  594.     if (pUniv->qualityMode == gxBestQuality)
  595.     {
  596.         newWDev |= kHighResBit;
  597.         pPrint->prJob.bJDocLoop = spool;
  598.     }
  599.     else
  600.     if (pUniv->qualityMode == gxFasterQuality)
  601.     {
  602.         pPrint->prJob.bJDocLoop = spool;
  603.     }
  604.     else    //    T => Draft quality
  605.     {
  606.         newWDev |= kDraftBit;
  607.         pPrint->prJob.bJDocLoop = draft;
  608.     }
  609.  
  610.     // Update the wDev field and the printX[1] field (a copy of wDev)
  611.     pPrint->prStl.wDev = newWDev;
  612.     pPrint->printX[1] = newWDev;
  613.     
  614.     
  615.     // Fix up the tray settings
  616.     {
  617.         short        firstTrayNum = tray1;
  618.         short        remainingTrayNum = tray1;
  619.         
  620.         switch (pUniv->firstTray)
  621.         {
  622.             case    gxFirstTray:        firstTrayNum = tray1;        break;
  623.             case    gxSecondTray:        firstTrayNum = tray2;        break;
  624.             case    gxThirdTray:        firstTrayNum = tray3;        break;
  625.         }
  626.         
  627.         switch (pUniv->remainingTray)
  628.         {
  629.             case    gxFirstTray:        remainingTrayNum = tray1;    break;
  630.             case    gxSecondTray:        remainingTrayNum = tray2;    break;
  631.             case    gxThirdTray:        remainingTrayNum = tray3;    break;
  632.         }
  633.         
  634.         pPrint->printX[0] = (remainingTrayNum << 2) | firstTrayNum;
  635.     }
  636.  
  637.     // Initialize some of the remaining fields in the TPrXInfo structure. PrValidate will fill in the rest
  638.     
  639.     pPrint->prXInfo.bUlThick = 0;
  640.     pPrint->prXInfo.bUlOffset = 0;
  641.     pPrint->prXInfo.bUlShadow = 0;
  642.     pPrint->prXInfo.bXInfoX = 0;
  643.  
  644.     return(noErr);
  645. }
  646. /* SD_ConvertPrintRecordFrom */
  647.  
  648.  
  649. /****************************************************************************************
  650.  
  651.                             SD_PrintRecordToJob
  652.                             
  653.     function:     
  654.                 SD_PrintRecordToJob is called by the Printing Manager when a print record
  655.                 needs to be converted into a job.  This driver takes this opportunity to
  656.                 add two collection items to the job, namely the one which specifies the
  657.                 desired head motion and the users tray selection.
  658.                 
  659.     parameters:    
  660.                 hPrint        print record to convert to a job
  661.                 theJob        job reference to use in converting the print record
  662.     
  663.     returns:
  664.                 OSErr
  665.     
  666. ****************************************************************************************/
  667. OSErr SD_PrintRecordToJob(THPrint hPrint, gxJob theJob)
  668. {
  669.     OSErr        anErr;
  670.     
  671.     // First forward the message so the job is created
  672.     anErr = Forward_GXPrintRecordToJob(hPrint, theJob);
  673.     require(anErr == noErr, Forward_GXPrintRecordToJob);
  674.     
  675.     // Add the collection item which specifies the desired head motion
  676.     {
  677.         HeadMotionJobItem        theMotion;
  678.         
  679.         theMotion.direction = (!TestBit((*hPrint)->prStl.wDev, kBiDirBit)) ? doUnidirectional : doBidirectional;
  680.         
  681.         anErr = AddCollectionItem(    GXGetJobCollection(theJob), 
  682.                                             kDrvrCreatorType, 
  683.                                             kHeadMotionItemIndex, 
  684.                                             sizeof(HeadMotionJobItem),
  685.                                             &theMotion);
  686.         require(anErr == noErr, AddHeadMotion);
  687.     }
  688.     
  689.     
  690.     // Add the collection item which specifies the desired tray settings
  691.     {
  692.         TraySettingsJobItem        theTraySettings;
  693.         
  694.         theTraySettings.firstPageFromTray = (*hPrint)->printX[0] & 0x0003;
  695.         theTraySettings.remainingFromTray = ((*hPrint)->printX[0] & 0x000C) >> 2;
  696.         
  697.         anErr = AddCollectionItem(    GXGetJobCollection(theJob), 
  698.                                             kDrvrCreatorType, 
  699.                                             kTraySettingsItemIndex, 
  700.                                             sizeof(TraySettingsJobItem),
  701.                                             &theTraySettings);
  702.         require(anErr == noErr, AddTraySettings);
  703.     }
  704.  
  705.  
  706. /******* Clean-up *******/
  707.  
  708. AddHeadMotion:
  709. AddTraySettings:
  710. Forward_GXPrintRecordToJob:
  711.     return(anErr);
  712. }
  713. /* SD_PrintRecordToJob */